/* eslint-disable no-undef */
/* eslint-disable @typescript-eslint/no-var-requires */
const express = require("express");
const router = express.Router();
const multer = require("multer");
const {
  accessSync,
  mkdirSync,
  writeFileSync,
  readdirSync,
  readFileSync,
  appendFileSync,
  unlinkSync,
  createWriteStream,
  createReadStream,
} = require("fs");
const { resolve, join } = require("path");
const { pipeline } = require("stream/promises");
const { unlink } = require("fs/promises");

// 文件上传
const storageDir = resolve(__dirname, "../uploads");
const storage = multer.memoryStorage();
const upload = multer({ storage }).single("file");

// 单片保存
// hash + chunkName
router.post("/", upload, function (req, res) {
  console.log(req.file, req.body);
  const storageHashContainerPath = join(storageDir, req.body.hash);
  const storageFilePath = join(storageHashContainerPath, req.body.chunkName);

  try {
    accessSync(storageFilePath);
    const msg = `当前片已存在`;
    res.json({ code: 0, msg });
  } catch (e) {
    try {
      accessSync(storageHashContainerPath);
    } catch (err) {
      mkdirSync(storageHashContainerPath, { recursive: true });
    }
    writeFileSync(storageFilePath, req.file.buffer);
    const msg = "当前片上传成功";
    res.json({ code: 0, msg });
  }
});

// 查询已经上传的片
// hash + fileName
router.get("/query", function (req, res) {
  console.log(req.query);
  const storageHashContainerPath = join(storageDir, req.query.hash);
  const storageFilePath = join(storageHashContainerPath, req.query.fileName);
  try {
    accessSync(storageFilePath);
    const msg = "文件已存在";
    res.json({ code: 0, msg });
  } catch (e) {
    try {
      accessSync(storageHashContainerPath);
      // 返回已上传的片
      const chunks = readdirSync(storageHashContainerPath);
      console.log(chunks);
      res.json({ code: 0, result: chunks });
    } catch (err) {
      // 从未上传过，一次全新的上传
      res.json({ code: 0, result: [] });
    }
  }
});

// 合并所有已经上传的片
// hash + fileName
router.get("/merge", function (req, res) {
  console.log(req.query);
  const storageHashContainerPath = join(storageDir, req.query.hash);
  const storageFilePath = join(storageHashContainerPath, req.query.fileName);
  try {
    accessSync(storageFilePath);
    const msg = "文件已存在";
    res.json({ code: 0, msg, result: storageFilePath });
  } catch (e) {
    try {
      accessSync(storageHashContainerPath);
      // 合并目录下所有的片，并清理碎片
      const chunks = readdirSync(storageHashContainerPath);
      console.log(chunks);
      // 筛选出分片(约定的分片命名为 `fileName_startBit`)
      const getKey = (ck) => +ck.split("_").slice(-1)[0];
      const numericAscend = (a, b) => +a - +b;
      const comparator = (a, b) => numericAscend(...[a, b].map(getKey));

      /* - sync - */
      // chunks
      //   .filter((ck) => ck.startsWith(req.query.fileName))
      //   .sort(comparator)
      //   .forEach((ck) => {
      //     console.log(ck);
      //     const chunkPath = join(storageHashContainerPath, ck);
      //     appendFileSync(storageFilePath, readFileSync(chunkPath));
      //     unlinkSync(chunkPath);
      //   });

      /* -stream- */
      const _chunks = chunks
        .filter((ck) => ck.startsWith(req.query.fileName))
        .sort(comparator);
      Promise.all(
        _chunks.map((ck) => {
          const chunkPath = join(storageHashContainerPath, ck);
          return pipeline(
            createReadStream(chunkPath),
            createWriteStream(storageFilePath, {
              start: getKey(ck),
            })
          );
        })
      ).then(() => {
        Promise.all(
          _chunks.map((ck) => {
            const chunkPath = join(storageHashContainerPath, ck);
            return unlink(chunkPath);
          })
        ).then(() => {
          res.json({ code: 0, msg: "文件上传成功", result: storageFilePath });
        });
      });
    } catch (err) {
      console.log(err);
      res.json({ code: 1, msg: "合并文件出错" });
    }
  }
});

module.exports = router;
